﻿#ifndef _C_HLS_TO_FMP4_HANDLER_H_
#define _C_HLS_TO_FMP4_HANDLER_H_

#include <string>
#include <fstream>
#include "FileCntl.h"
extern "C"
{
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
#include "libavutil/timestamp.h"
};

class CHlsToMp4Handler
{
public:
	enum DataType {
		DATA_HEADER,
		DATA_SYNC_POINT,
		DATA_BOUNDARY_POINT,
		DATA_UNKNOWN,
		DATA_TRAILER,
		DATA_FLUSH_POINT,
	};
	CHlsToMp4Handler();
	~CHlsToMp4Handler();
	int initialize(const char* inputFile, const char* outputFile);
	void deinitialize();
	int openInput(const char* url);
	int openOutput(const char* filePath);
	int openMp4Output(const char* filePath);
	void closeInput();
	void closeOutput();
	void closeMp4Output();

	int run();

	static int64_t io_seek(void* opaque, int64_t offset, int whence);

	static int io_write(void* opaque, uint8_t* buf, int size);

	static int io_write_data_type(void* opaque, uint8_t* buf, int size,
		enum AVIODataMarkerType type, int64_t time);

	DataType mapType(AVIODataMarkerType type);

protected:
	virtual int64_t muxerSeek(int64_t offset, int whence);

	virtual int muxerWrite(uint8_t* buf, int size);

	int write(uint8_t* buf, int size);

	virtual int muxerWriteDataType(uint8_t* buf, int size, DataType type, int64_t time);

	void resizeFile();
private:
	bool inited = false;
	bool workFlag = false;
	std::string strOutFile = "";
	AVFormatContext* ifmt_ctx = NULL;
	unsigned char* avio_buffer = NULL;
	AVFormatContext* ofmt_ctx = nullptr;
	AVPacket pkt;
	int audioIndex = -1;
	int videoIndex = -1;
	int stream_index = 0;
	int* stream_mapping = NULL;
	int stream_mapping_size;
	int width = 0, height = 0;
	int64_t last_dts = 0;
	int64_t first_pts_dts = 0;
	int first_pkt = 0;
	FileCntl* fpPosterior = nullptr;
	char* writeTemp = nullptr;
	int tempSize = 1024 * 1024 * 1;
	int validData = 0;
	uint64_t lastSeekSize = 0;
};

#endif	// _C_HLS_TO_FMP4_HANDLER_H_
